#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <queue>
#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <sstream>
#include <type_traits>
#include <iomanip>
#include <chrono>
#include <ctime>

class AsyncLogger {
public:
    // 日志级别枚举
    enum class LogLevel {
        DEBUG,    // 调试信息，最详细的日志级别
        INFO,     // 一般信息，记录程序运行状态
        WARNING,  // 警告信息，可能出现问题但不影响运行
        ERROR     // 错误信息，需要关注的问题
    };

    // 初始化日志系统
    // 参数:
    //   filename - 日志文件路径，默认为"app.log"
    //   level - 记录的最低日志级别，默认为INFO
    //   maxQueueSize - 日志队列最大容量，默认为10000
    static void Init(const std::string& filename = "app.log", 
                    LogLevel level = LogLevel::INFO,
                    size_t maxQueueSize = 10000) {
        Instance().Initialize(filename, level, maxQueueSize);
    }

    // 停止日志系统，确保所有日志被写入
    static void Shutdown() {
        Instance().Stop();
    }

    // 通用日志记录接口
    // 参数:
    //   level - 日志级别
    //   format - 带占位符的格式字符串
    //   args - 可变参数，用于替换占位符
    template<typename... Args>
    static void Log(LogLevel level, const std::string& format, Args&&... args) {
        Instance().EnqueueLog(level, format, std::forward<Args>(args)...);
    }

    // 以下是不同日志级别的快捷方法
    template<typename... Args>
    static void Debug(const std::string& format, Args&&... args) {
        Log(LogLevel::DEBUG, format, std::forward<Args>(args)...);
    }

    template<typename... Args>
    static void Info(const std::string& format, Args&&... args) {
        Log(LogLevel::INFO, format, std::forward<Args>(args)...);
    }

    template<typename... Args>
    static void Warning(const std::string& format, Args&&... args) {
        Log(LogLevel::WARNING, format, std::forward<Args>(args)...);
    }

    template<typename... Args>
    static void Error(const std::string& format, Args&&... args) {
        Log(LogLevel::ERROR, format, std::forward<Args>(args)...);
    }

private:
    // 单例模式实现，确保全局只有一个日志实例
    static AsyncLogger& Instance() {
        static AsyncLogger instance;  // 线程安全的局部静态变量(C++11保证)
        return instance;
    }

    // 日志消息结构体
    struct LogMessage {
        std::string message;  // 格式化后的日志消息
        LogLevel level;       // 日志级别
        std::chrono::system_clock::time_point timestamp;  // 时间戳

        LogMessage(const std::string& msg, LogLevel lvl)
            : message(msg), level(lvl), timestamp(std::chrono::system_clock::now()) {}
    };

    // 线程安全日志队列实现
    class LogQueue {
    public:
        // 构造函数，初始化队列最大容量
        LogQueue(size_t maxSize) : maxSize_(maxSize), stopped_(false) {}

        // 向队列添加日志(生产者调用)
        // 参数:
        //   msg - 要添加的日志消息(右值引用，避免拷贝)
        // 返回值:
        //   true - 添加成功
        //   false - 日志系统已停止
        bool Enqueue(LogMessage&& msg) {
            std::unique_lock<std::mutex> lock(mutex_);
            // 等待队列不满或系统停止
            notFull_.wait(lock, [this]() { return queue_.size() < maxSize_ || stopped_; });
            
            if (stopped_) return false;
            
            queue_.emplace(std::move(msg));  // 移动语义添加消息
            notEmpty_.notify_one();          // 通知消费者有新消息
            return true;
        }

        // 从队列取出日志(消费者调用)
        // 参数:
        //   msg - 用于接收取出的日志
        // 返回值:
        //   true - 取出成功
        //   false - 队列为空且系统已停止
        bool Dequeue(LogMessage& msg) {
            std::unique_lock<std::mutex> lock(mutex_);
            // 等待队列不空或系统停止
            notEmpty_.wait(lock, [this]() { return !queue_.empty() || stopped_; });
            
            if (stopped_ && queue_.empty()) return false;
            
            msg = std::move(queue_.front());  // 移动语义取出消息
            queue_.pop();
            notFull_.notify_one();            // 通知生产者有空位
            return true;
        }

        // 停止队列，唤醒所有等待线程
        void Stop() {
            {
                std::lock_guard<std::mutex> lock(mutex_);
                stopped_ = true;  // 设置停止标志
            }
            // 通知所有等待线程
            notEmpty_.notify_all();
            notFull_.notify_all();
        }

    private:
        std::queue<LogMessage> queue_;       // 实际存储日志的队列
        const size_t maxSize_;               // 队列最大容量
        std::mutex mutex_;                   // 保护队列的互斥锁
        std::condition_variable notEmpty_;   // 队列不空的条件变量
        std::condition_variable notFull_;    // 队列不满的条件变量
        std::atomic<bool> stopped_;          // 停止标志(原子操作保证线程安全)
    };

    // 日志格式化工具类
    class Formatter {
    public:
        // 格式化主接口
        // 参数:
        //   format - 带{}占位符的格式字符串
        //   args - 可变参数，用于替换占位符
        template<typename... Args>
        static std::string Format(const std::string& format, Args&&... args) {
            // 先将所有参数转为字符串
            std::vector<std::string> strArgs = {ToString(std::forward<Args>(args))...};
            return FormatImpl(format, strArgs);  // 调用实际格式化实现
        }

    private:
        // 实际格式化实现
        // 参数:
        //   format - 带{}占位符的格式字符串
        //   args - 已转换为字符串的参数列表
        static std::string FormatImpl(const std::string& format, const std::vector<std::string>& args) {
            std::string result;     // 结果字符串
            size_t argIndex = 0;    // 当前参数索引
            size_t pos = 0;         // 当前处理位置
            size_t len = format.length();  // 格式字符串长度

            // 遍历格式字符串
            while (pos < len) {
                if (format[pos] == '{' && pos + 1 <len) {
                    // 检测到 { 开头
                    size_t end_pos = format.find('}', pos + 1);
                    if (end_pos == std::string::npos) {
                        // 未闭合的 {
                        result += format[pos++];
                        continue;
                    }
                    
                    // 提取 {} 内部内容（如 :.1f）
                    std::string spec = format.substr(pos + 1, end_pos - pos - 1);
                    if (argIndex < args.size()) {
                        // 这里可以添加对 spec 的解析逻辑
                        result += args[argIndex++]; // 简单实现（暂不支持格式说明符）
                    } else {
                        result += "{}";
                    }
                    pos = end_pos + 1;
                } else {
                    result += format[pos++];
                }
            }

            // 处理多余的参数(追加到日志末尾)
            while (argIndex < args.size()) {
                if (!result.empty() && result.back() != ' ') {
                    result += " ";  // 添加分隔空格
                }
                result += args[argIndex++];
            }

            return result;
        }

        // 类型转换工具，将各种类型转为字符串
        template<typename T>
        static std::string ToString(T&& value) {
            using Type = std::decay_t<T>;  // 移除引用和const限定

            // 根据类型选择最佳转换方式
            // 把最具体的类型检查放在前面通常更清晰

            if constexpr (std::is_same_v<Type, std::string>) {
                return value;  // 已经是字符串
            }
            // --- 修改开始 ---
            else if constexpr (std::is_same_v<Type, const char*>) {
                // 显式检查 C 风格字符串是否为 null
                return (value != nullptr) ? std::string(value) : std::string("nullptr");
            } else if constexpr (std::is_same_v<Type, char*>) {
                // 同样检查可变的 C 风格字符串
                return (value != nullptr) ? std::string(value) : std::string("nullptr");
            }
            // --- 修改结束 ---
            else if constexpr (std::is_same_v<Type, std::nullptr_t>) {
                // 处理字面量 nullptr
                return "nullptr";
            } else if constexpr (std::is_convertible_v<Type, std::string>) {
                 // 例如 std::string_view (放在 bool 和 arithmetic 之前可能更好)
                return std::string(value);
            } else if constexpr (std::is_same_v<Type, bool>) {
                return value ? "true" : "false";
            } else if constexpr (std::is_arithmetic_v<Type>) { // bool 已被上面处理
                return std::to_string(value);  // 数值类型
            } else {
                // 其他类型使用流操作符
                std::ostringstream oss;
                // C++20 之前流不能直接处理 nullptr_t，但这里应该已经被 nullptr_t 分支捕获
                // 如果需要处理 boolalpha:
                // if constexpr (std::is_same_v<Type, bool>) {
                //     oss << std::boolalpha << value;
                // } else {
                //     oss << value;
                // }
                oss << value;
                return oss.str();
            }
        }
    };

    // 成员变量
    std::unique_ptr<LogQueue> logQueue_;  // 线程安全日志队列
    std::ofstream logFile_;              // 日志文件输出流
    std::thread workerThread_;           // 后台写入线程
    std::atomic<bool> running_{false};   // 运行状态标志
    LogLevel logLevel_;                  // 当前日志级别

    // 私有构造函数(单例模式)
    AsyncLogger() = default;
    // 析构函数确保资源释放
    ~AsyncLogger() {
        Stop();
    }

    // 实际初始化方法
    void Initialize(const std::string& filename, LogLevel level, size_t maxQueueSize) {
        if (running_) return;  // 防止重复初始化

        // 打开日志文件(追加模式)
        logFile_.open(filename, std::ofstream::out | std::ofstream::app);
        if (!logFile_.is_open()) {
            throw std::runtime_error("Failed to open log file: " + filename);
        }

        logLevel_ = level;  // 设置日志级别
        logQueue_ = std::make_unique<LogQueue>(maxQueueSize);  // 创建队列
        running_ = true;  // 设置运行标志
        // 启动后台工作线程
        workerThread_ = std::thread(&AsyncLogger::WorkerThreadFunc, this);
    }

    // 停止日志系统
    void Stop() {
        if (!running_) return;

        running_ = false;      // 设置停止标志
        logQueue_->Stop();     // 停止队列

        if (workerThread_.joinable()) {
            workerThread_.join();  // 等待工作线程结束
        }

        if (logFile_.is_open()) {
            logFile_.close();  // 关闭日志文件
        }
    }

    // 将日志加入队列
    template<typename... Args>
    void EnqueueLog(LogLevel level, const std::string& format, Args&&... args) {
        if (level < logLevel_) return;  // 低于当前日志级别则忽略

        try {
            // 格式化日志消息
            std::string formatted = Formatter::Format(format, std::forward<Args>(args)...);
            // 加入队列
            logQueue_->Enqueue(LogMessage(formatted, level));
        } catch (const std::exception& e) {
            std::cerr << "Log formatting error: " << e.what() << std::endl;
        }
    }

    // 后台工作线程函数
    void WorkerThreadFunc() {
        LogMessage msg("", LogLevel::INFO);
        
        // 主循环: 运行中或队列不为空时继续处理
        while (running_ || logQueue_->Dequeue(msg)) {
            if (msg.level >= logLevel_) {
                WriteToFile(msg);  // 写入文件
            }
        }

        // 确保队列中剩余日志被写入
        while (logQueue_->Dequeue(msg)) {
            if (msg.level >= logLevel_) {
                WriteToFile(msg);
            }
        }
    }

    // 将日志写入文件
    void WriteToFile(const LogMessage& msg) {
        if (!logFile_.is_open()) return;

        try {
            // 转换时间戳为本地时间
            auto time = std::chrono::system_clock::to_time_t(msg.timestamp);
            std::tm tm;
            localtime_r(&time, &tm);  // 线程安全的时间转换

            // 写入日志文件
            logFile_ << "[" << std::put_time(&tm, "%Y-%m-%d %H:%M:%S") << "] "
                     << LevelToString(msg.level) << ": " << msg.message << std::endl;
        } catch (const std::exception& e) {
            std::cerr << "Log write error: " << e.what() << std::endl;
        }
    }

    // 日志级别转字符串
    std::string LevelToString(LogLevel level) {
        switch (level) {
            case LogLevel::DEBUG: return "DEBUG";
            case LogLevel::INFO: return "INFO";
            case LogLevel::WARNING: return "WARNING";
            case LogLevel::ERROR: return "ERROR";
            default: return "UNKNOWN";
        }
    }
};


#include <vector>

// 测试自定义类型的日志输出
struct User {
    int id;
    std::string name;
    
    friend std::ostream& operator<<(std::ostream& os, const User& user) {
        return os << "User[id=" << user.id << ", name=" << user.name << "]";
    }
};

void TestBasicFunctions() {
    std::cout << "=== Testing basic logging functions ===" << std::endl;
    
    // 测试不同日志级别
    AsyncLogger::Debug("This is a debug message");
    AsyncLogger::Info("This is an info message");
    AsyncLogger::Warning("This is a warning message");
    AsyncLogger::Error("This is an error message");
    
    // 测试占位符替换
    AsyncLogger::Info("User {} logged in at {}", "Alice", "2025-01-01 12:00:00");
    AsyncLogger::Info("Current temperature: {:.1f}°C", 23.5);
    
    // 测试参数数量不匹配
    AsyncLogger::Info("Missing {} arguments {}", "one");       // 预期: Missing one arguments {}
    AsyncLogger::Info("Extra arguments {}", "one", "two");     // 预期: Extra arguments one two
    
    // 测试不同类型参数
    AsyncLogger::Info("Integer: {}, Double: {:.2f}, String: {}", 42, 3.14159, "hello");
    AsyncLogger::Info("Boolean: { }, Nullptr: { }", true, nullptr);
    
    // 测试自定义类型
    User user{1, "Bob"};
    AsyncLogger::Info("User details: {}", user);
}

void TestMultithreading() {
    std::cout << "\n=== Testing multithreaded logging ===" << std::endl;
    
    const int THREAD_COUNT = 5;
    const int LOGS_PER_THREAD = 100;
    
    std::vector<std::thread> threads;
    
    for (int i = 0; i < THREAD_COUNT; ++i) {
        threads.emplace_back([i]() {
            for (int j = 0; j < LOGS_PER_THREAD; ++j) {
                AsyncLogger::Info("Thread {} - Message {}", i, j);
            }
        });
    }
    
    for (auto& t : threads) {
        t.join();
    }
    
    AsyncLogger::Info("All logging threads completed");
}

void TestPerformance() {
    std::cout << "\n=== Testing performance ===" << std::endl;
    
    const int TOTAL_LOGS = 1000;
    auto start = std::chrono::high_resolution_clock::now();
    
    for (int i = 0; i < TOTAL_LOGS; ++i) {
        AsyncLogger::Info("Performance test message {}", i);
    }
    
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
    
    // 输出性能信息
    AsyncLogger::Info("Logged {} messages in {} ms ({} msg/sec)", 
                     TOTAL_LOGS, duration, 
                     static_cast<int>(TOTAL_LOGS / (duration / 1000.0)));
}

void TestLogLevelFiltering() {
    std::cout << "\n=== Testing log level filtering ===" << std::endl;
    
    // 重新初始化，设置日志级别为WARNING
    AsyncLogger::Shutdown();
    AsyncLogger::Init("filtered.log", AsyncLogger::LogLevel::WARNING);
    
    // 这些日志应该被记录
    AsyncLogger::Warning("This warning should appear");
    AsyncLogger::Error("This error should appear");
    
    // 这些日志应该被过滤掉
    AsyncLogger::Debug("This debug should NOT appear");
    AsyncLogger::Info("This info should NOT appear");
    
    // 恢复默认日志级别
    AsyncLogger::Shutdown();
    AsyncLogger::Init("app.log", AsyncLogger::LogLevel::DEBUG);
}

void TestExceptionHandling() {
    std::cout << "\n=== Testing exception handling ===" << std::endl;
    
    // 测试文件打开失败
    try {
        AsyncLogger::Init("/invalid/path/to/logfile.log");
    } catch (const std::exception& e) {
        std::cerr << "Expected exception: " << e.what() << std::endl;
    }
    
    // 恢复正常的日志文件
    AsyncLogger::Init("app.log");
    
    // 测试格式化异常
    try {
        // 故意传递错误的格式字符串
        AsyncLogger::Info("Bad format {", 42);
    } catch (...) {
        AsyncLogger::Error("Caught formatting exception (expected)");
    }
}

int main() {
    // 初始化日志系统
    AsyncLogger::Init("app.log", AsyncLogger::LogLevel::DEBUG);
    
    // 测试各项功能
    TestBasicFunctions();
    TestMultithreading();
    TestPerformance();
    TestLogLevelFiltering();
    TestExceptionHandling();
    
    // 关闭日志系统
    AsyncLogger::Shutdown();
    
    std::cout << "\nAll tests completed. Check log files for output." << std::endl;
    return 0;
}